﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Text;

namespace HalconDotNet
{
	/// <summary>
	///   The HALCON vector classes are intended to support the export of
	///   HDevelop code that uses vectors, and to pass vector arguments to
	///   procedures that use vector parameters. They are not intended to be
	///   used as generic container classes in user code. For this purpose,
	///   consider using standard container classes such as List&lt;T&gt;.
	///
	///   Also note HVector is abstract, you can only create instances
	///   of HTupleVector or HObjectVector.
	/// </summary>
	// Token: 0x0200009F RID: 159
	public abstract class HVector : ICloneable, IDisposable
	{
		// Token: 0x06001FE4 RID: 8164 RVA: 0x000BAA2B File Offset: 0x000B8C2B
		protected HVector(int dimension)
		{
			if (dimension < 0)
			{
				throw new HVectorAccessException("Invalid vector dimension " + dimension);
			}
			this.mDimension = dimension;
			this.mVector = ((dimension > 0) ? new List<HVector>() : null);
		}

		// Token: 0x06001FE5 RID: 8165 RVA: 0x000BAA68 File Offset: 0x000B8C68
		protected HVector(HVector vector) : this(vector.Dimension)
		{
			if (this.mDimension > 0)
			{
				this.mVector.Capacity = vector.Length;
				for (int i = 0; i < vector.Length; i++)
				{
					this.mVector.Add(vector[i].Clone());
				}
			}
		}

		// Token: 0x06001FE6 RID: 8166 RVA: 0x000BAAC4 File Offset: 0x000B8CC4
		[EditorBrowsable(EditorBrowsableState.Never)]
		public void TransferOwnership(HVector source)
		{
			if (source == this)
			{
				return;
			}
			if (source != null && source.Dimension != this.Dimension)
			{
				throw new HVectorAccessException("Vector dimension mismatch");
			}
			this.Dispose();
			if (source == null)
			{
				return;
			}
			if (this.mDimension > 0)
			{
				this.mVector = source.mVector;
				source.mVector = new List<HVector>();
				GC.ReRegisterForFinalize(this);
				return;
			}
			throw new HVectorAccessException("TransferOwnership not implemented for leaf");
		}

		// Token: 0x170000A0 RID: 160
		// (get) Token: 0x06001FE7 RID: 8167 RVA: 0x000BAB2F File Offset: 0x000B8D2F
		public int Dimension
		{
			get
			{
				return this.mDimension;
			}
		}

		// Token: 0x170000A1 RID: 161
		// (get) Token: 0x06001FE8 RID: 8168 RVA: 0x000BAB38 File Offset: 0x000B8D38
		public int Length
		{
			get
			{
				if (this.mDimension <= 0)
				{
					return 0;
				}
				List<HVector> obj = this.mVector;
				int count;
				lock (obj)
				{
					count = this.mVector.Count;
				}
				return count;
			}
		}

		// Token: 0x06001FE9 RID: 8169 RVA: 0x000BAB84 File Offset: 0x000B8D84
		[EditorBrowsable(EditorBrowsableState.Never)]
		public void AssertDimension(int dimension)
		{
			if (this.mDimension != dimension)
			{
				throw new HVectorAccessException("Expected vector dimension " + dimension);
			}
		}

		// Token: 0x06001FEA RID: 8170 RVA: 0x000BABA8 File Offset: 0x000B8DA8
		private void AssertSize(int index)
		{
			if (this.mVector == null)
			{
				return;
			}
			List<HVector> obj = this.mVector;
			lock (obj)
			{
				int count = this.mVector.Count;
				if (index >= count)
				{
					this.mVector.Capacity = index + 1;
					for (int i = count; i <= index; i++)
					{
						this.mVector.Add(this.GetDefaultElement());
					}
				}
			}
		}

		// Token: 0x06001FEB RID: 8171
		protected abstract HVector GetDefaultElement();

		/// <summary>
		///   Access to subvector at specified index. The vector will be
		///   enlarged to accomodate index, even in read access. For read
		///   access without enlargement use the member function At(index).
		///   A reference to the internal subvector is returned and needs
		///   to be cloned for independent manipulation.
		/// </summary>
		// Token: 0x170000A2 RID: 162
		public HVector this[int index]
		{
			get
			{
				if (this.mDimension < 1 || index < 0)
				{
					throw new HVectorAccessException("Index out of range");
				}
				this.AssertSize(index);
				List<HVector> obj = this.mVector;
				HVector result;
				lock (obj)
				{
					result = this.mVector[index];
				}
				return result;
			}
			set
			{
				if (this.mDimension < 1 || index < 0)
				{
					throw new HVectorAccessException("Index out of range");
				}
				if (value.Dimension != this.mDimension - 1)
				{
					throw new HVectorAccessException("Vector dimension mismatch");
				}
				this.AssertSize(index);
				List<HVector> obj = this.mVector;
				HVector hvector;
				lock (obj)
				{
					hvector = this.mVector[index];
					this.mVector[index] = value.Clone();
				}
				hvector.Dispose();
			}
		}

		/// <summary>
		///   Read access to subvector at specified index. In contrast
		///   to the index operator, an exception will be raised if index
		///   is out of range. A reference to the internal subvector is
		///   returned and needs to be cloned for independent manipulation.
		/// </summary>
		// Token: 0x06001FEE RID: 8174 RVA: 0x000BAD14 File Offset: 0x000B8F14
		public HVector At(int index)
		{
			if (this.mDimension < 1 || index < 0 || index >= this.Length)
			{
				throw new HVectorAccessException("Index out of range");
			}
			List<HVector> obj = this.mVector;
			HVector result;
			lock (obj)
			{
				result = this.mVector[index];
			}
			return result;
		}

		// Token: 0x06001FEF RID: 8175 RVA: 0x000BAD78 File Offset: 0x000B8F78
		protected virtual bool EqualsImpl(HVector vector)
		{
			if (vector.Dimension != this.Dimension)
			{
				return false;
			}
			if (vector.Length != this.Length)
			{
				return false;
			}
			if (this.mDimension > 0)
			{
				for (int i = 0; i < this.Length; i++)
				{
					if (!this[i].VectorEqual(vector[i]))
					{
						return false;
					}
				}
			}
			return true;
		}

		/// <summary>
		///   Returns true if vector has same dimension, lengths, and elements
		/// </summary>
		// Token: 0x06001FF0 RID: 8176 RVA: 0x000BADD7 File Offset: 0x000B8FD7
		public bool VectorEqual(HVector vector)
		{
			return vector.GetType() == base.GetType() && this.EqualsImpl(vector);
		}

		// Token: 0x06001FF1 RID: 8177 RVA: 0x000BADF0 File Offset: 0x000B8FF0
		protected HVector ConcatImpl(HVector vector, bool append, bool clone)
		{
			if (this.mDimension < 1 || vector.Dimension != this.mDimension)
			{
				throw new HVectorAccessException("Vector dimension mismatch");
			}
			HVector hvector = append ? this : this.Clone();
			hvector.mVector.Capacity = this.Length + vector.Length;
			for (int i = 0; i < vector.Length; i++)
			{
				hvector.mVector.Add(clone ? vector[i].Clone() : vector[i]);
			}
			return hvector;
		}

		/// <summary>
		///   Concatenate two vectors, creating new vector
		/// </summary>
		// Token: 0x06001FF2 RID: 8178 RVA: 0x000BAE79 File Offset: 0x000B9079
		public HVector Concat(HVector vector)
		{
			return this.ConcatImpl(vector, false, true);
		}

		// Token: 0x06001FF3 RID: 8179 RVA: 0x000BAE84 File Offset: 0x000B9084
		[EditorBrowsable(EditorBrowsableState.Never)]
		public HVector Concat(HVector vector, bool clone)
		{
			return this.ConcatImpl(vector, false, clone);
		}

		/// <summary>
		///   Append vector to this vector
		/// </summary>
		// Token: 0x06001FF4 RID: 8180 RVA: 0x000BAE8F File Offset: 0x000B908F
		public HVector Append(HVector vector)
		{
			return this.ConcatImpl(vector, true, true);
		}

		// Token: 0x06001FF5 RID: 8181 RVA: 0x000BAE9A File Offset: 0x000B909A
		[EditorBrowsable(EditorBrowsableState.Never)]
		public HVector Append(HVector vector, bool clone)
		{
			return this.ConcatImpl(vector, true, clone);
		}

		// Token: 0x06001FF6 RID: 8182 RVA: 0x000BAEA8 File Offset: 0x000B90A8
		protected void InsertImpl(int index, HVector vector, bool clone)
		{
			if (this.mDimension < 1 || vector.Dimension != this.mDimension - 1)
			{
				throw new HVectorAccessException("Vector dimension mismatch");
			}
			if (index < 0)
			{
				throw new HVectorAccessException("Index out of range");
			}
			this.AssertSize(index - 1);
			List<HVector> obj = this.mVector;
			lock (obj)
			{
				this.mVector.Insert(index, clone ? vector.Clone() : vector);
			}
		}

		/// <summary>
		///   Insert vector at specified index
		/// </summary>
		// Token: 0x06001FF7 RID: 8183 RVA: 0x000BAF30 File Offset: 0x000B9130
		public HVector Insert(int index, HVector vector)
		{
			this.InsertImpl(index, vector, true);
			return this;
		}

		// Token: 0x06001FF8 RID: 8184 RVA: 0x000BAF3C File Offset: 0x000B913C
		[EditorBrowsable(EditorBrowsableState.Never)]
		public HVector Insert(int index, HVector vector, bool clone)
		{
			this.InsertImpl(index, vector, clone);
			return this;
		}

		// Token: 0x06001FF9 RID: 8185 RVA: 0x000BAF48 File Offset: 0x000B9148
		protected void RemoveImpl(int index)
		{
			if (this.mDimension < 1)
			{
				throw new HVectorAccessException("Vector dimension mismatch");
			}
			if (index >= 0 && index < this.Length)
			{
				List<HVector> obj = this.mVector;
				lock (obj)
				{
					this.mVector[index].Dispose();
					this.mVector.RemoveAt(index);
				}
			}
		}

		/// <summary>
		///   Remove element at specified index from this vector
		/// </summary>
		// Token: 0x06001FFA RID: 8186 RVA: 0x000BAFBC File Offset: 0x000B91BC
		public HVector Remove(int index)
		{
			this.RemoveImpl(index);
			return this;
		}

		// Token: 0x06001FFB RID: 8187 RVA: 0x000BAFC8 File Offset: 0x000B91C8
		protected virtual void ClearImpl()
		{
			if (this.mDimension < 1)
			{
				throw new HVectorAccessException("Vector dimension mismatch");
			}
			List<HVector> obj = this.mVector;
			lock (obj)
			{
				for (int i = 0; i < this.Length; i++)
				{
					this.mVector[i].Dispose();
				}
				this.mVector.Clear();
			}
		}

		/// <summary>
		///   Remove all elements from this vector
		/// </summary>
		// Token: 0x06001FFC RID: 8188 RVA: 0x000BB03C File Offset: 0x000B923C
		public HVector Clear()
		{
			this.ClearImpl();
			return this;
		}

		// Token: 0x06001FFD RID: 8189
		protected abstract HVector CloneImpl();

		// Token: 0x06001FFE RID: 8190 RVA: 0x000BB045 File Offset: 0x000B9245
		object ICloneable.Clone()
		{
			return this.CloneImpl();
		}

		// Token: 0x06001FFF RID: 8191 RVA: 0x000BB045 File Offset: 0x000B9245
		[EditorBrowsable(EditorBrowsableState.Never)]
		public HVector Clone()
		{
			return this.CloneImpl();
		}

		// Token: 0x06002000 RID: 8192 RVA: 0x00020D0B File Offset: 0x0001EF0B
		protected virtual void DisposeLeafObject()
		{
		}

		/// <summary>
		///   Clear vector and dispose elements (if necessary). When called
		///   on vector with dimension &gt; 0 the effect is identical to clear
		/// </summary>
		// Token: 0x06002001 RID: 8193 RVA: 0x000BB04D File Offset: 0x000B924D
		public void Dispose()
		{
			GC.SuppressFinalize(this);
			if (this.mDimension > 0)
			{
				this.Clear();
				return;
			}
			this.DisposeLeafObject();
		}

		/// <summary>
		///   Provides a simple string representation of the vector,
		///   which is mainly useful for debug outputs.
		/// </summary>
		// Token: 0x06002002 RID: 8194 RVA: 0x000BB06C File Offset: 0x000B926C
		public override string ToString()
		{
			if (this.mDimension <= 0)
			{
				return "";
			}
			StringBuilder stringBuilder = new StringBuilder();
			stringBuilder.Append("{");
			for (int i = 0; i < this.Length; i++)
			{
				if (i != 0)
				{
					stringBuilder.Append(", ");
				}
				stringBuilder.Append(this[i].ToString());
			}
			stringBuilder.Append("}");
			return stringBuilder.ToString();
		}

		// Token: 0x0400118C RID: 4492
		internal int mDimension;

		// Token: 0x0400118D RID: 4493
		protected List<HVector> mVector;
	}
}
